﻿using CommunityToolkit.Mvvm.ComponentModel;
using Cyl.Communication;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
using VisionApp.Startup.Models;

namespace VisionApp.Startup.Services;

public   class CommunicationService
{
    private bool isConnnected;

    public bool IsConnected
    {
        get { return isConnnected; }
        set {
            if (isConnnected != value)
            {
                isConnnected = value;
                OnIsConnectedChanged.Invoke(this,value);
            }            
        }
    }


    public event EventHandler<ProductType> OnProductTypeChanged;
    public event EventHandler<string> OnTrigSignalChanged;
    public event EventHandler<bool> OnIsConnectedChanged;

    private ProductTypeDictionary productDic;
    private ICommDevice? commDevice;
    private readonly ILogger<CommunicationService> logger;
    private DispatcherTimer? _timer;

    public CommunicationService(ILogger<CommunicationService> logger)
    {
        this.logger = logger;

        var stringDic = File.ReadAllText(Path.Combine(Constants.BaseConfigPath, "ProductTypeDictionary.json"));
        productDic = JsonConvert.DeserializeObject<ProductTypeDictionary>(stringDic);
    }
    public ICommDevice? GetCommDevice(string ip)
    {
        if (commDevice != null) 
        { 
            return commDevice;
        }
         commDevice = CommDeviceFactory.CreateCommDevicePlcSiemence(ip,Path.Combine("config", "VariableList.json"));

        if (commDevice == null)
        {
            logger.LogError("连接通信设备失败");
        }
        else
        {
            commDevice.OnDataChanged += CommDevice_OnDataChanged;
            commDevice.OnTrigCamera += OnTrigCamera;
            commDevice.OnDisconnect += CommDevice_OnDisconnect;
            IsConnected = true;
        }

        _timer = new();
        _timer.Interval = TimeSpan.FromMilliseconds(1000);
        _timer.Tick += _timer_Tick;
        _timer.Start();

        return commDevice;
    }
    private void CommDevice_OnDataChanged(object sender, StringEventArgs e)
    {
#if DEBUG
        Debug.WriteLine($"一个遗忘的bug{e.VarName}={e.NewValue}");
#endif
        // 切换产品类型，不主动读取产品类型，可以节省通信时间。PLC要在触发信号之前设置产品类型
        if(e.VarName.Contains( "ProductType"))
        {            
            string cameraName="";
            if (e.VarName.Length > 11) 
            {
                var cameraIndex = Convert.ToInt32( e.VarName.Substring(11, 1))-1;
                cameraName = $"Camera{cameraIndex}"; 
            }
           var product=Convert.ToInt32(e.NewValue);
            // 映射到产品类型字典
            var type= productDic.ProductTypes.Find(t=>t.PlcValue==product);
            if (type != null) {
                type.PlcValue = product;
                type.CameraName = cameraName;
                // 发送给vm
                OnProductTypeChanged?.Invoke(this, type);
            }
        }
    }
    // 收到触发信号后，自动执行算法
    private void OnTrigCamera(object sender, StringEventArgs e)
    {
        if (commDevice == null)
        {
            logger.LogError("没有连接PLC");
            return;
        }
        var indexStr = e.Message;
        var index=Convert.ToInt32(indexStr)-1;// 相机的索引
        OnTrigSignalChanged?.Invoke(this, $"Camera{index}");
    }
    private void CommDevice_OnDisconnect(object sender, string e)
    {
        // TODO 处理断开连接后 no Implementation
        IsConnected = false;
    }
    private async void _timer_Tick(object sender, EventArgs e)
    {
        try
        {
            await Task.Run(() => { commDevice?.ReadVar("HeartbeatSignal"); });
            IsConnected = true;
            _timer.Interval = TimeSpan.FromSeconds(5);
        }
        catch (Exception)
        {
            IsConnected = false;
            _timer.Interval = TimeSpan.FromSeconds(30);
        }
    }

}
